package com.yoda.youdianda.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sun.corba.se.impl.orbutil.ObjectStreamClassUtil_1_3;
import com.yoda.youdianda.common.R;
import com.yoda.youdianda.common.RC;
import com.yoda.youdianda.common.ThreadContext;
import com.yoda.youdianda.domain.*;
import com.yoda.youdianda.exception.BusinessException;
import com.yoda.youdianda.exception.RegException;
import com.yoda.youdianda.mapper.*;
import com.yoda.youdianda.service.*;
import com.yoda.youdianda.util.JwtUtils;
import com.yoda.youdianda.vo.*;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shawn
 * @date 2022年 11月 12日 22:17
 */
@Service
public class SystemServiceImpl implements SystemService {

    /**
     * 此处已在启动类上定义mapper扫描
     */
    @Autowired
    private SystemMapper systemMapper;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Autowired
    private SystemUserService systemUserService;

    @Autowired
    private SystemService systemService;

    @Autowired
    private YddUserService yddUserService;

    @Autowired
    private SysRoleService sysRoleService;

    @Resource
    private SysMenuService sysMenuService;

    @Autowired
    private SysDictService sysDictService;

    @Autowired
    private YddCateService yddCateService;

    @Resource
    private YddCateMapper yddCateMapper;

    @Autowired
    private YddAdvposService yddAdvposService;

    @Autowired
    private YddArticleService yddArticleService;

    @Resource
    private YddArticleMapper yddArticleMapper;

    @Autowired
    private YddTagService yddTagService;

    @Autowired
    private YddAdvimgService yddAdvimgService;

    @Resource
    private YddAdvimgMapper yddAdvimgMapper;

    @Resource
    private YddLinkMapper yddLinkMapper;

    @Resource
    private YddUserDataMapper yddUserDataMapper;

    @Resource
    private YddUserMapper yddUserMapper;

    @Override
    public R<SysConfigVo> getConfig() {
        LambdaQueryWrapper<SysConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SysConfig::getTabValue, "system");
        wrapper.eq(SysConfig::getDelFlag,0);
        List<SysConfig> configs = systemMapper.selectList(wrapper);
        //找出对应的字段,封装vo对象
        Map<String, SysConfig> configMap = CollUtil.fieldValueMap(configs, "attrKey");
        SysConfigVo vo = new SysConfigVo();
        //根据对应字段找出对应的值,封装vo
        if (!Objects.isNull(configMap.get("login_title"))) {
            vo.setLogin_title(configMap.get("login_title").getAttrValue());
        }
        if (!Objects.isNull(configMap.get("login_bg"))) {
            vo.setLogin_bg(configMap.get("login_bg").getAttrValue());
        }
        if (!Objects.isNull(configMap.get("system_name"))) {
            vo.setSystem_name(configMap.get("system_name").getAttrValue());
        }
        if (!Objects.isNull(configMap.get("system_logo"))) {
            vo.setSystem_logo(configMap.get("system_logo").getAttrValue());
        }
        if (!Objects.isNull(configMap.get("web_ico"))) {
            vo.setWeb_ico(configMap.get("web_ico").getAttrValue());
        }
        return R.success(vo, 0);
    }

    /**
     * 根据用户登录名查找用户
     *
     * @param login_name 登录名
     * @return {@link SysUser}
     */
    @Override
    public SysUser selectUserByLoginName(String login_name) {
        return systemUserService.selectUserByLoginName(login_name);
    }

    @Override
    public ProfileVo getProfile(String userId) {
        SimpleDateFormat format = new SimpleDateFormat(RC.GENERAL_DATE_FORMAT);
        ProfileVo profileVo = new ProfileVo();
        UserInfoVo vo = new UserInfoVo();
        //1 查询个人配置
        SysUser user = systemUserService.selectUserById(userId);
        //封装vo
        BeanUtils.copyProperties(user, vo);
        vo.setDefault_data(user.getDefaultData());
        vo.setLogin_name(user.getLoginName());
        vo.setLogin_ip(user.getLoginIp());
        String login_date = format.format(user.getLoginDate());
        String create_date = format.format(user.getCreateDate());
        Date updateDate = user.getUpdateDate();
        if (!Objects.isNull(updateDate)) {
            String update_date = format.format(updateDate);
            vo.setUpdate_date(update_date);
        }

        vo.setLogin_date(login_date);
        vo.setCreate_date(create_date);
        vo.setDel_flag(user.getDelFlag());

        //处理角色id
        List<String> role_id = JSON.parseObject(user.getRoleId(), List.class);


        vo.setRole_id(role_id);
        // 2 根据role_id集合查询角色信息
        List<SysRole> roles = sysRoleService.getRoleByIds(role_id);
        //封装角色名
        List<String> rolename = new ArrayList<>();
        //改装成字符数组集合
        //遍历角色
        for (SysRole role : roles) {
            rolename.add(role.getName());
        }
        vo.setRolename(rolename);

        profileVo.setUserInfo(vo);
        //根据当前用户角色id查询所有菜单id 再查询所有菜单
//        List<SysMenu> menus = sysMenuService.getAllByIds(role_id);
        //todo
        List<SysMenu> menus = sysMenuService.getAll();
        //转换vo
        List<SysMenu> lists = menus.stream().filter(s -> !StringUtils.isEmpty(s.getPath()) && !StringUtils.isEmpty(s.getComponent())).collect(Collectors.toList());

        List<MenuVo> menuList = lists.stream().map((menu) -> {
            MenuVo menuVo = new MenuVo();
            BeanUtils.copyProperties(menu, menuVo);
            menuVo.setDel_flag(menu.getDelFlag());
            menuVo.setIs_show(menu.getIsShow());
            menuVo.setIs_cache(menu.getIsCache());
            menuVo.setIs_link(menu.getIsLink());
            menuVo.setDefault_data(menu.getDefaultData());
            Date create = menu.getCreateDate();
            Date update = menu.getUpdateDate();
            String c = format.format(create);
            if (!Objects.isNull(update)) {
                String u = format.format(update);
                menuVo.setUpdate_date(u);
            }
            menuVo.setCreate_date(c);
            return menuVo;
        }).collect(Collectors.toList());
        profileVo.setMenuList(menuList);
        //查询所有表类型
        List<SysDict> dicts = sysDictService.getAll();

        Map<String, String> table_type = new HashMap<>();
        Map<String, String> interface_type = new HashMap<>();
        Map<String, String> report_type = new HashMap<>();
        Map<String, String> theme = new HashMap<>();
        Map<String, String> order_type = new HashMap<>();
        for (SysDict dict : dicts) {
            if ("table_type".equals(dict.getType())) {
                table_type.put(dict.getValue(), dict.getLabel());
            } else if ("interface_type".equals(dict.getType())) {
                interface_type.put(dict.getValue(), dict.getLabel());
            } else if ("report_type".equals(dict.getType())) {
                report_type.put(dict.getValue(), dict.getLabel());
            } else if ("theme".equals(dict.getType())) {
                theme.put(dict.getValue(), dict.getLabel());
            } else if ("order_type".equals(dict.getType())) {
                order_type.put(dict.getValue(), dict.getLabel());
            }
        }
        MapVo mapVo = new MapVo();
        mapVo.setTable_type(table_type);
        mapVo.setInterface_type(interface_type);
        mapVo.setReport_type(report_type);
        mapVo.setTheme(theme);
        mapVo.setOrder_type(order_type);
        profileVo.setDictsList(mapVo);
        List<String> btnList = new ArrayList<>();
        btnList.add("*");
        profileVo.setBtnList(btnList);
        return profileVo;
    }

    /**
     * 获取后台系统基本信息
     *
     * @return {@link BaseInfoVo}
     */
    @Override
    public BaseInfoVo getBaseInfo() {
        BaseInfoVo vo = new BaseInfoVo();
        //获取所有分类信息
        List<YddCate> cates = yddCateService.getAllCate();

        //获取所有文章信息
        List<YddArticle> articles = yddArticleService.getAllArticles();
        //初始化vo ->all_cate
        List<YddCateVo> all_cate = cates.stream().map(cate ->
                YddCateVo.init(cate, articles)
        ).collect(Collectors.toList());
        vo.setAll_cate(all_cate);
        //广告位总数
        Integer advpos_num = yddAdvposService.countAdvpos();
        vo.setAdvpos_num(advpos_num);
        //标签总数
        Integer tag_num = yddTagService.countTags();
        vo.setTag_num(tag_num);
        //管理员总数
        Integer admin_num = systemUserService.countUsers();
        vo.setAdmin_num(admin_num);
        //文章总数
        Integer article_num = articles.size();
        vo.setArticle_num(article_num);
        //分类总数
        Integer cate_num = cates.size();
        vo.setCate_num(cate_num);
        //广告图总数
        Integer advimg_num = yddAdvimgService.countAdvImg();
        vo.setAdvimg_num(advimg_num);
        //最新注册用户
        List<YddUser> users = yddUserService.getAllUser();
        List<YddUser> new_user = new ArrayList<>();
        for (int i = 0; users.size() > 7 ? i < 6 : i < users.size(); i++) {
            new_user.add(users.get(i));
        }
        vo.setNew_user(new_user);
        //推荐热文
        List<YddArticle> hot_article = articles.stream().filter(article -> article.getIshot() == 1).collect(Collectors.toList());
        vo.setHot_article(hot_article);
        UserCountVo user = UserCountVo.init(users);
        vo.setUser(user);
        return vo;
    }

    @Override
    public void updateUser(SysUser sysUser) {
        systemUserService.updateUser(sysUser);
    }

    /**
     * 前台首页和全局
     *
     * @return
     */
    @Override
    public HomePageVo getIndex() {

        //获取所有分类
        List<YddCate> yddCateList = yddCateService.getAllCate();
        //获取配置数据
        LambdaQueryWrapper<SysConfig> delWrapper = new LambdaQueryWrapper<>();
        //添加逻辑删除字段delFlag为0(正常)1(删除)
        delWrapper.eq(SysConfig::getDelFlag,0);
        //获取逻辑删除字段为0 的数据
        List<SysConfig> sysConfigList = systemMapper.selectList(delWrapper);

        //嵌套三个VO-list
        List<SettingsVo> list = new ArrayList<>();

        //list和allData都会封装到这里
        FrontConfigVo frontConfigVo = new FrontConfigVo();

        //2 获取所有的设置分类 预期:分类集合
        ArrayList<String> tabs = new ArrayList<>();  //用于下面存放tab引入组件名称
        ArrayList<String> groups = new ArrayList<>(); //用于下面存放配置名称

        List<MiniConfigVo> allData = new ArrayList<>();

        Map<String, String> formMap = new HashMap<>();//设置表里attr_key -> attr_value
        Map<String, String> rulesMap = new HashMap<>();//设置表里attr_key -> validator 不为空的字段映射
        for (SysConfig config : sysConfigList) {
            //参数不为空,且tabs不包含则添加进入集合
            if (!Strings.isEmpty(config.getTabValue()) && !tabs.contains(config.getTabValue())) {
                tabs.add(config.getTabValue());
            }
            //参数不为空,且groups不包含则添加进入集合
            if (Strings.isNotEmpty(config.getGroupValue()) && !groups.contains(config.getGroupValue())) {
                groups.add(config.getGroupValue());
            }
            MiniConfigVo miniConfigVo = MiniConfigVo.init(config);
            allData.add(miniConfigVo);


            formMap.put(config.getAttrKey(), config.getAttrValue());
            if (Strings.isNotEmpty(config.getValidator())) {
                rulesMap.put(config.getAttrKey(), config.getValidator());
            }
        }

        //3 根据参数集合查找对应设置集合

        for (String tab : tabs) {
            List<ChildrenConfigVo> children = new ArrayList<>();
            //获取未细分的设置
            List<SysConfig> filter1 = sysConfigList.stream().filter(s -> tab.equals(s.getTabValue())).collect(Collectors.toList());
            //对设置按组进行细分
            for (String group : groups) {
                List<SysConfig> filter2 = filter1.stream().filter(s -> group.equals(s.getGroupValue())).collect(Collectors.toList());
                //转化vo
                if (filter2.size() > 0) {
                    ChildrenConfigVo childrenConfigVo = ChildrenConfigVo.init(group, filter2);
                    children.add(childrenConfigVo);
                }
            }
            SettingsVo settingsVo = SettingsVo.init(tab, children);
            list.add(settingsVo);
        }
        //vo  list部分完成
        frontConfigVo.setList(list);
        frontConfigVo.setAllData(allData);



        //获取所有标签
        List<YddTag> yddTagList = yddTagService.list();
        List<YddTagVo> yddTagVos = yddTagList.stream().map(YddTagVo::init).collect(Collectors.toList());
        //获取所有友情链接
        List<YddLink> yddLinkList = yddLinkMapper.selectList(new LambdaQueryWrapper<>());
        //获取轮播图数据
        LambdaQueryWrapper<YddAdvimg> wrapper = new LambdaQueryWrapper<>();
        //添加条件广告图位置,关联广告位id
        wrapper.eq(YddAdvimg::getAdvimgpos, "15");
        List<YddAdvimg> yddAdvimgList = yddAdvimgMapper.selectList(wrapper);
        //获取侧边栏图片
        LambdaQueryWrapper<YddAdvimg> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(YddAdvimg::getAdvimgpos, "14");
        List<YddAdvimg> yddAdvimgList1 = yddAdvimgMapper.selectList(wrapper1);
        //获取详情广告图
        LambdaQueryWrapper<YddAdvimg> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.in(YddAdvimg::getAdvimgpos, Arrays.asList("13","12"));
        List<YddAdvimg> yddAdvimgList2 = yddAdvimgMapper.selectList(wrapper2);

        //创建vo对象封装数据
        HomePageVo homePageVo = new HomePageVo();
        homePageVo.setAllCate(yddCateList);
        homePageVo.setConfig(frontConfigVo);
        homePageVo.setAllTag(yddTagVos);
        homePageVo.setAllLink(yddLinkList);
        homePageVo.setBanner(yddAdvimgList);
        homePageVo.setSideBanner(yddAdvimgList1);
        homePageVo.setShowBanner(yddAdvimgList2);

        return homePageVo;
    }

    /**
     * 前台热门置顶文章数据
     * @param page
     * @param limit
     * @return
     */
    @Override
    public HotVo getnew(String page, String limit) {
        //获取当前时间
        long time = new Date().getTime();
        //获取24小时最新文章数量
        long time1 = time - 86400000L;
        LambdaQueryWrapper<YddArticle> wrapper = new LambdaQueryWrapper<>();
        //wrapper.ne(YddArticle::getStatus,3);
        //添加文章是否是发布状态的文章2
        wrapper.eq(YddArticle::getStatus,2);
        //添加创建时间大于等于
        wrapper.ge(YddArticle::getCreateDate,time1);
        Integer integer = yddArticleMapper.selectCount(wrapper);
        //获取一周最新文章数量
        long timeWeek = time - 604800000L;
        LambdaQueryWrapper<YddArticle> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.ge(YddArticle::getCreateDate,timeWeek);
        Integer integer1 = yddArticleMapper.selectCount(wrapper1);

        long pageLong = Long.parseLong(page);
        long limitLong = Long.parseLong(limit);

        //分页构造器
        Page<YddArticle> yddArticlePageResult = new Page<>(pageLong, limitLong);
        //条件构造器
        LambdaQueryWrapper<YddArticle> wrapper2 = new LambdaQueryWrapper<>();
        //执行分页查询
        yddArticleMapper.selectPage(yddArticlePageResult,wrapper2);

        List<YddArticle> data = yddArticlePageResult.getRecords();
        ArrayList<RAticlesVo> rAticlesVoArrayList = new ArrayList<>();
        for (YddArticle datum : data) {
            //获取每个数据对应的分类名称
            Integer cateid = datum.getCateid();
            YddCate yddCate = yddCateMapper.selectById(cateid);
            String catename = yddCate.getCatename();
            //把catename传给RAticlesVo对象
            RAticlesVo rAticlesVo = new RAticlesVo();
            BeanUtils.copyProperties(datum,rAticlesVo);
            rAticlesVo.setCatename(catename);
            rAticlesVoArrayList.add(rAticlesVo);
        }
        //获取总数/总页数/每页数量/当前页码
        PageResult<RAticlesVo> rAticlesVoPageResult = new PageResult<>(Integer.parseInt(page),Integer.parseInt(limit),(int)yddArticlePageResult.getTotal(),rAticlesVoArrayList);
        //把数据封装到vo中
        HotVo hotVo = new HotVo();
        hotVo.setDesc("首页大列表");
        hotVo.setNum_day(integer);
        hotVo.setNum_week(integer1);
        hotVo.setList(rAticlesVoPageResult);
        return hotVo;
    }

    /**
     * 前台文章列表展示
     * @param page
     * @param limit
     * @param cateid
     * @return
     */
    @Override
    public ArticleListDataVo getlist(String page, String limit, String cateid) {
        //转换数据类型
        long pageLong = Long.parseLong(page);
        long limitLong = Long.parseLong(limit);
        long cateidLong = Long.parseLong(cateid);
        //分页构造器
        Page<YddArticle> pr = new Page<>(pageLong, limitLong);
        //条件构造器
        LambdaQueryWrapper<YddArticle> wrapper = new LambdaQueryWrapper<>();
        //添加分类条件,根据cateid进行排序
        wrapper.eq(!ObjectUtils.isEmpty(cateid),YddArticle::getCateid,cateidLong);
        //逻辑删除字段校验
        wrapper.ne(YddArticle::getStatus,3);
        //置顶排序,热门排序
        wrapper.orderByDesc(YddArticle::getIstop).orderByDesc(YddArticle::getIshot);
        //分页查询
        yddArticleMapper.selectPage(pr,wrapper);
        PageResult<RAticlesVo> pageResult = new PageResult<>();
        //将pr赋值给pageResult
        BeanUtils.copyProperties(pr,pageResult);

        ArrayList<RAticlesVo> list = new ArrayList<>();
        List<YddArticle> getdata = pr.getRecords();
        //遍历分页数据
        for (YddArticle getdatum : getdata) {
            //获取每个数据对应的分类名称
            YddCate yddCate = yddCateMapper.selectById(cateidLong);
            String catename = yddCate.getCatename();
            RAticlesVo rAticlesVo = new RAticlesVo();
            BeanUtils.copyProperties(getdatum,rAticlesVo);
            rAticlesVo.setCatename(catename);
            list.add(rAticlesVo);
        }
        pageResult.setData(list);
        //将数据封装到vo
        ArticleListDataVo articleListDataVo = new ArticleListDataVo();
        articleListDataVo.setList(pageResult);

        return articleListDataVo;
    }

    /**
     * 前台最新文章
     * @return
     */
    @Override
    public RArticlessVo gethot() {
        //创建条件构造器
        LambdaQueryWrapper<YddArticle> wrapper = new LambdaQueryWrapper<>();
        //添加排序条件,根据收藏数量进行排序
        wrapper.orderByDesc(YddArticle::getLovenum);
        //文章状态
        wrapper.ne(YddArticle::getStatus,3);

        ArrayList<RAticlesVo> list = new ArrayList<>();
        //进行条件查询
        List<YddArticle> yddArticles = yddArticleMapper.selectList(wrapper);
        //循环获取六条展示数据
        for (int i = 0; i < (Math.min(yddArticles.size(), 6)); i++) {
            //根据文章分类id查询所归属的分类标签数据
            YddCate yddCate = yddCateMapper.selectById(yddArticles.get(i).getCateid());
            RAticlesVo rAticlesVo = new RAticlesVo();
            BeanUtils.copyProperties(yddArticles.get(i),rAticlesVo);
            //再获取分类名称
            rAticlesVo.setCatename(yddCate.getCatename());
            list.add(rAticlesVo);
        }
        //将数据封装到vo
        RArticlessVo rArticlessVo = new RArticlessVo();
        rArticlessVo.setList(list);

        return rArticlessVo;
    }

    /**
     * 前台文章详情数据
     * @param id
     * @return
     */
    @Override
    public ArticleDetailsDataVo getshow(Integer id) {

        YddArticle yddArticle = yddArticleMapper.selectById(id);
        //更新文章点击数
        yddArticle.setClick(yddArticle.getClick()+1);
        yddArticleMapper.updateById(yddArticle);
        YddCate yddCate = yddCateMapper.selectById(yddArticle.getCateid());
        String catename = yddCate.getCatename();

        RAticlesVo rAticlesVo = new RAticlesVo();
        BeanUtils.copyProperties(yddArticle,rAticlesVo);
        rAticlesVo.setCatename(catename);
        //创建条件构造器
//        LambdaQueryWrapper<YddUserData> wrapper = new LambdaQueryWrapper<>();
        //todo 该请求未被拦截,无法获取token 添加排序条件
        String userId = ThreadContext.getId(RC.YDD_ID);
//        wrapper.eq(YddUserData::getUserId,userId).eq(YddUserData::getArticleId,yddArticle.getId());
//        List<YddUserData> yddUserData = yddUserDataMapper.selectList(wrapper);

        String key = RC.ARTICLE_KEY+id+RC.USER_ID_VALUE+userId;
        String likeValue =RC.BEHAVIOR_VALUE+RC.LIKE_VALUE ;
        String collectValue =RC.BEHAVIOR_VALUE+RC.COLLECT_VALUE ;
        Boolean isLiked = redisTemplate.opsForHash().hasKey(key, likeValue);
        Boolean isCollect = redisTemplate.opsForHash().hasKey(key, collectValue);
        rAticlesVo.setIsCollect(isLiked);
        rAticlesVo.setIsLike(isCollect);
//        if (ObjectUtils.isEmpty(yddUserData)){
//            rAticlesVo.setIsCollect(false);
//            rAticlesVo.setIsLike(false);
//        }else if (yddUserData.size()==1){
//            YddUserData yddUserData1 = yddUserData.get(0);
//            Integer type = yddUserData1.getType();
//            if (type==1){
//                rAticlesVo.setIsLike(false);
//            }else {
//                rAticlesVo.setIsCollect(false);
//            }
//        }
        //把文章详情数据set到info
        ArticleDetailsDataVo articleDetailsDataVo = new ArticleDetailsDataVo();
        articleDetailsDataVo.setInfo(rAticlesVo);

        //获取上一篇id数据
        YddArticle yddArticle1 = yddArticleMapper.selectById(yddArticle.getId() - 1);
        if (ObjectUtils.isEmpty(yddArticle1)){
            ArrayList<String> list = new ArrayList<>();
            articleDetailsDataVo.setPrev(list);
        }else {
            ArrayList<YddArticle> yddArticles = new ArrayList<>();
            yddArticles.add(yddArticle1);
            articleDetailsDataVo.setPrev(yddArticles);
        }

        //获取下一篇id数据
        YddArticle yddArticle2 = yddArticleMapper.selectById(yddArticle.getId() + 1);
        if (ObjectUtils.isEmpty(yddArticle2)){
            articleDetailsDataVo.setNext(null);
        }else {
            ArrayList<YddArticle> yddArticles2 = new ArrayList<>();
            yddArticles2.add(yddArticle2);
            articleDetailsDataVo.setNext(yddArticles2);
        }

        //推荐文章数据
        LambdaQueryWrapper<YddArticle> wrapper1 = new LambdaQueryWrapper<>();
        //添加排序条件,是否是推荐文章
        wrapper1.eq(YddArticle::getIshot,1);
        List<YddArticle> yddArticles = yddArticleMapper.selectList(wrapper1);
        ArrayList<YddArticle> list = new ArrayList<>();
        for (YddArticle article : yddArticles) {
            if (list.size() < 8) {
                list.add(article);
            }
        }
        articleDetailsDataVo.setRecommend(list);

        return articleDetailsDataVo;
    }

}